package com.aplink.generic.controller;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;

import com.aplink.generic.database.DatabaseHelper;
import com.aplink.generic.pojo.GenericObject;
import com.aplink.generic.pojo.ObjPropInfo;
import com.aplink.generic.util.convertcount.GenericFilter;

import java.util.ArrayList;
import java.util.HashMap;

public class SessionManager {

    // apply Singleton pattern with synchronisation to escape multi-thread
    // access
    private static SessionManager instance;

    // Context
    private Context _context = null;

    @SuppressWarnings("rawtypes")
    private final Class _loginClass;

    // Editor for Shared preferences
    private Editor editor = null;

    // Shared Preferences
    private SharedPreferences pref = null;

    public static SessionManager getInstance() {
        return instance;
    }

    /**
     * escape multi-thread access by using double-checked locking
     * http://www.ibm.com/developerworks/java/library/j-dcl/index.html escape
     * multi-processor access, out-of-order writes
     */

    @SuppressWarnings("rawtypes")
    public static SessionManager setInstance( Context context, Class loginClass,
                                              String databaseName, int tableStructureFileId, int tableDataFileId ) {
        if ( instance == null ) {
            synchronized ( SessionManager.class ) {
                final SessionManager inst = instance;
                if ( inst == null ) {
                    synchronized ( SessionManager.class ) {
                        instance = new SessionManager( context, loginClass );

                        instance.createDataBaseFirstStart( databaseName,
                                tableStructureFileId, tableDataFileId );
                    }
                }
            }
        }
        return instance;
    }

    // Constructor
    @SuppressWarnings("rawtypes")
    private SessionManager( Context context, Class loginClass ) {
        this._context = context;
        this._loginClass = loginClass;
        this.pref = this._context.getSharedPreferences(
                ControllerParameter.PACKAGE_NAME, Context.MODE_PRIVATE );
        this.editor = this.pref.edit();
    }

    private boolean createDatabaseAndDemoData( String databaseName,
                                               int tableStructureFileId, int tableDataFileId ) {

        // final DatabaseHelper mDBHelper = new DatabaseHelper(this._context);
        //
        // final boolean isStructureSuccessful = mDBHelper.initiateStructure(
        // this._context, tableStructureFileId);
        // final boolean isDataSuccessful =
        // mDBHelper.initiateData(this._context,
        // tableDataFileId);

        // return (isStructureSuccessful && isDataSuccessful);
        return true;
    }

    // check with database whether our database is existed or not
    private boolean createDataBaseFirstStart( String databaseName,
                                              int tableStructureFileId, int tableDataFileId ) {
        boolean isSucessful = true;
        final int firstStarted = this.pref.getInt(
                ControllerParameter.FIRST_STARTED, 0 );
        if ( firstStarted == 0 ) {
            isSucessful = this.createDatabaseAndDemoData( databaseName,
                    tableStructureFileId, tableDataFileId );
            if ( isSucessful ) {
                this.editor.putInt( ControllerParameter.FIRST_STARTED, 1 );
                this.editor.commit();
            }
        }

        return isSucessful;
    }

    /**
     * Reset whole data of app
     */
    private void resetSessionApp() {
        // Clearing Login session from Shared Preferences

        this.editor.clear();
        this.editor.commit();

        // After reset, we redirect user to Log -in Activity
        final Intent i = new Intent( this._context, this._loginClass );
        // Closing all the Activities
        i.addFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP );

        // Add new Flag to start new Activity
        i.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK );

        // Staring Login Activity
        this._context.startActivity( i );
    }

    /**
     * Check login method wil check user login status If false it will redirect
     * user to login page Else won't do anything
     */
    public void checkLogin() {
        // Check login status
        if ( ! this.isLoggedIn() ) {
            // user is not logged in redirect him to Login Activity
            final Intent i = new Intent( this._context, this._loginClass );
            // Closing all the Activities
            i.addFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP );

            // Add new Flag to start new Activity
            i.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK );

            // Staring Login Activity
            this._context.startActivity( i );
        }

    }

    public boolean createLoginSession( DatabaseHelper mDbManager,
                                       String userTable, ArrayList<ObjPropInfo> mObjectPropInfo,
                                       GenericObject userInfo ) {
        // firstly we should check with DB about this account, throw false value
        // in default case;
//		final GenericObject mainGenericObject = mDbManager
//				.getObjectByObjPropInfo(mObjectPropInfo, userInfo);
        // if (mainGenericObject == null) {
        // return false;
        // }

        ObjPropInfo accountIdInfo = new ObjPropInfo();
        ObjPropInfo accountPassInfo = new ObjPropInfo();

        accountIdInfo = GenericFilter
                .getObjPropInfoOfAccountId( mObjectPropInfo );
        accountPassInfo = GenericFilter
                .getObjPropInfoOfAccountPass( mObjectPropInfo );

        if ( ( accountIdInfo == null ) || ( accountPassInfo == null ) ) {
            return false;
        }

        // Storing login value as TRUE
        this.editor.putBoolean( ControllerParameter.IS_LOGIN, true );

        // Storing attribute KEY_TABLE (the table store account information) for
        // shareprecerence, and find the value inside this genericObject in pref
        this.editor.putString( ControllerParameter.KEY_TABLE_ACCOUNT, userTable );

        // Storing attribute KEY_NAME for shareprecerence, and find the value
        // inside this genericObject in pref
        this.editor.putString( ControllerParameter.KEY_ACCOUNTID, userInfo
                .getContentFromAttributeName( accountIdInfo.getObjectProperty() )
                .toString() );

        // Storing password as an attribute KEY_PASS for shareprecerence, and
        // find the value inside this genericObject pref
        this.editor.putString(
                ControllerParameter.KEY_ACCOUNTPASS,
                userInfo.getContentFromAttributeName(
                        accountPassInfo.getObjectProperty() ).toString() );

        // commit changes
        this.editor.commit();

        return true;
    }

    /**
     * Get stored session data
     */
    public HashMap<String, String> getUserDetails() {
        final HashMap<String, String> user = new HashMap<String, String>();

        // table user
        user.put( ControllerParameter.KEY_TABLE_ACCOUNT, this.pref.getString(
                ControllerParameter.KEY_TABLE_ACCOUNT, null ) );

        // user name
        user.put( ControllerParameter.KEY_ACCOUNTID,
                this.pref.getString( ControllerParameter.KEY_ACCOUNTID, null ) );

        // user password

        user.put( ControllerParameter.KEY_ACCOUNTPASS,
                this.pref.getString( ControllerParameter.KEY_ACCOUNTPASS, null ) );

        // return user
        return user;
    }

    /**
     * Quick check for login *
     */
    public boolean isLoggedIn() {
        return this.pref.getBoolean( ControllerParameter.IS_LOGIN, false );
    }

    /**
     * Clear log-in session details
     */
    public void logoutUser( Context mContext ) {
        // Clearing Login session from Shared Preferences
        this.editor.remove( ControllerParameter.IS_LOGIN );
        this.editor.remove( ControllerParameter.KEY_ACCOUNTID );
        this.editor.remove( ControllerParameter.KEY_ACCOUNTPASS );

        this.editor.commit();

        this._context = mContext;
        // After logout, redirect user to Loing Activity
        final Intent i = new Intent( this._context, this._loginClass );
        // Closing all the Activities
        // i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

        // Add new Flag to start new Activity
        i.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK );

        // Staring Login Activity
        this._context.startActivity( i );
    }

    public void resetDbAndSessionForApp( String databaseName ) {
        this._context.deleteDatabase( databaseName );
        this.resetSessionApp();
    }

}
